﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using Microsoft.Lync.Model;

namespace LyncStatusChanger
{
	public sealed class LyncManager
	{
		private readonly LyncClient client;

		private bool _connected;

		public LyncManager()
		{
			try
			{
				client = LyncClient.GetClient();
				if (client.State == ClientState.SignedIn)
					Connected = true;
			}
			catch (Exception)
			{
				throw new LyncNotRunningException();
			}
			client.StateChanged += myClient_ClientStateChanged;
		}

		public bool Connected
		{
			get { return _connected; }
			set
			{
				_connected = value;
				OnConectadoChanged();
			}
		}

		public void ChangePersonalNote(string personalNote)
		{
			if (client.State == ClientState.SignedIn)
			{
				var publishData = new Dictionary<PublishableContactInformationType, object>();

				publishData.Add(PublishableContactInformationType.PersonalNote, personalNote);
				SendPublishRequest(publishData, "NotaPersonal");
			}
			else
			{
				throw new LyncNotSignedInException();
			}
		}

		public string ObtenerNotaPersonalActual()
		{
			if (client.State == ClientState.SignedIn)
			{
				try
				{
					return client.Self.Contact.GetContactInformation(ContactInformationType.PersonalNote).ToString();
				}
				catch (Exception)
				{
					return "";
				}
			}
			else
			{
				return "";
			}
		}

		private void myClient_ClientStateChanged(object source, ClientStateChangedEventArgs data)
		{
			if (data.NewState == ClientState.SignedIn)
			{
				Connected = true;
				//MessageBox.Show("Signed in");
				return;
			}
			if (data.NewState == ClientState.SignedOut)
			{
				Connected = false;
				return;
			}

			if (data.NewState == ClientState.ShuttingDown)
			{
				Connected = false;
				return;
			}

			//MessageBox.Show(data.NewState.ToString());
		}

		/// <summary>
		/// Sends a publication request and handles any exceptions raised.
		/// </summary>
		/// <param name="publishData">Dictionary. Information to be published.</param>
		/// <param name="PublishId">string. Unique publication identifier.</param>
		private void SendPublishRequest(
			Dictionary<PublishableContactInformationType, object> publishData,
			string PublishId)
		{
			object publishState = PublishId;
			object[] _PublishAsyncState = {client.Self, publishState};
			try
			{
				client.Self.BeginPublishContactInformation(
					publishData,
					null,
					_PublishAsyncState);
			}
			catch (COMException ce)
			{
				//MessageBox.Show("publish COM exception: " + ce.ErrorCode.ToString());
			}
			catch (ArgumentException ae)
			{
				//MessageBox.Show("publish Argument exception: " + ae.Message);
			}
		}

		//varas de eventos

		public event EventHandler ConectadoChanged;

		private void OnConectadoChanged()
		{
			EventHandler handler = ConectadoChanged;
			if (handler != null)
			{
				handler(this, new EventArgs());
			}
		}
	}

	[Serializable]
	public class LyncNotRunningException : Exception
	{
		public LyncNotRunningException()
		{
		}

		public LyncNotRunningException(string message) : base(message)
		{
		}

		public LyncNotRunningException(string message, Exception inner) : base(message, inner)
		{
		}

		protected LyncNotRunningException(
			SerializationInfo info,
			StreamingContext context)
			: base(info, context)
		{
		}
	}

	[Serializable]
	public class LyncNotSignedInException : Exception
	{
		public LyncNotSignedInException()
		{
		}

		public LyncNotSignedInException(string message) : base(message)
		{
		}

		public LyncNotSignedInException(string message, Exception inner) : base(message, inner)
		{
		}

		protected LyncNotSignedInException(
			SerializationInfo info,
			StreamingContext context)
			: base(info, context)
		{
		}
	}
}